package top.littlejiang.onlinexam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import top.littlejiang.onlinexam.common.base.BaseServiceImpl;
import top.littlejiang.onlinexam.common.base.BusinessException;
import top.littlejiang.onlinexam.common.utils.JWTUtils;
import top.littlejiang.onlinexam.entity.OlexamExam;
import top.littlejiang.onlinexam.entity.OlexamStuScore;
import top.littlejiang.onlinexam.entity.OlexamUser;
import top.littlejiang.onlinexam.mapper.OlexamExamMapper;
import top.littlejiang.onlinexam.service.OlexamCourseService;
import top.littlejiang.onlinexam.service.OlexamExamService;
import top.littlejiang.onlinexam.service.OlexamStuAnswerService;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 考试表 服务实现类
 * </p>
 *
 * @author chen
 * @since 2021-03-11
 */
@Service
public class OlexamExamServiceImpl extends BaseServiceImpl<OlexamExamMapper, OlexamExam> implements OlexamExamService {

    @Autowired
    OlexamExamMapper examMapper;
    @Autowired
    OlexamCourseService courseService;
    @Autowired
    OlexamStuAnswerService stuAnswerService;
    /**
     * 列表查询
     * @param query
     * @return
     */
    @Override
    public List<OlexamExam> getListForTeacher(OlexamExam query) {
        List<Integer> courseIds = courseService.selectIdsByTeacher(JWTUtils.getUserId(), query.getFkCourseName());
        if (CollectionUtils.isEmpty(courseIds)){
            throw new BusinessException("查询结果为空！");
        }
        List<OlexamExam> list = examMapper.getExamList(listWrapper(query, courseIds));
        return list;
    }

    /**
     * 列表查询
     *
     * @param query
     * @return
     */
    @Override
    public List<OlexamExam> getListForStu(OlexamExam query) {
        List<Serializable> courseIds = courseService.selectIdsByUser(JWTUtils.getUserId(), query.getFkCourseName());
        if (CollectionUtils.isEmpty(courseIds)){
            throw new BusinessException("查询结果为空！");
        }
        QueryWrapper<OlexamExam> wrapper = new QueryWrapper<>();
        wrapper.eq("is_del", 0);
        wrapper.in("fk_course_id", courseIds);
        if (StringUtils.isNotBlank(query.getExamName())){
            wrapper.like("exam_name",query.getExamName());
        }
        if (!CollectionUtils.isEmpty(query.getStatusList())){
            wrapper.in("status", query.getStatusList());
        }
        return list(wrapper);
    }

    /**
     * 列表查询条件
     * @param query
     * @param courseIds
     * @return
     */
    private QueryWrapper<OlexamExam> listWrapper(OlexamExam query, List<Integer> courseIds){
        QueryWrapper<OlexamExam> wrapper = new QueryWrapper<>();
        wrapper.eq("exam.is_del", 0);
        wrapper.in("fk_course_id", courseIds);
        if (StringUtils.isNotBlank(query.getExamName())){
            wrapper.like("exam_name",query.getExamName());
        }
        return wrapper;
    }

    /**
     * 获取所有不重复考试名
     *
     * @return
     */
    @Override
    public List<String> getNames() {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.select("distinct exam_name");
        wrapper.eq("is_del", 0);
        List<String> list = this.listObjs(wrapper);
        return list;
    }

    /**
     * 根据考试名获取考试id
     *
     * @param examName
     * @return
     */
    @Override
    public String getUuidByNames(String examName) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.select("distinct exam_uuid");
        wrapper.eq("exam_name", examName);
        wrapper.eq("is_del", 0);
        OlexamExam olexamExam = selectOne(wrapper);
        return olexamExam.getExamUuid();
    }

    /**
     * 检查是否已存在考试名
     *
     * @param examName
     * @return
     */
    @Override
    public boolean checkName(String examName) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("exam_name", examName);
        List list = this.list(wrapper);
        return !CollectionUtils.isEmpty(list);
    }

    /**
     * 根据uuid 逻辑删除
     *
     * @param uuids
     */
    @Override
    public void deleteByUuid(List<String> uuids) {
        UpdateWrapper wrapper = new UpdateWrapper();
        wrapper.set("is_del", 1);
        wrapper.in("exam_uuid", uuids);
        this.update(wrapper);
    }

    /**
     * 根据uuid 更新考试状态
     * @param examUuid
     * @param status
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateStatus(String examUuid, Integer status) {
        UpdateWrapper wrapper = new UpdateWrapper();
        wrapper.set("status", status);
        wrapper.eq("exam_uuid", examUuid);
        this.update(wrapper);
    }

    /**
     * 根据uuid 查询单个
     *
     * @param query
     * @return
     */
    @Override
    public OlexamExam checkOne(OlexamExam query) {
        QueryWrapper<OlexamExam> wrapper = new QueryWrapper();
        wrapper.eq("is_del", 0).eq("exam_uuid", query.getExamUuid());
        List<OlexamExam> list = list(wrapper);
        if (CollectionUtils.isEmpty(list)){
            throw new BusinessException("查询错误！");
        }
        return list.get(0);
    }

    /**
     * 查询考试统计结果
     *
     * @param examUuid
     * @return
     */
    @Override
    public Map<String, Object> getExamRst(String examUuid) {
        List<OlexamUser> mapperRst = getBaseMapper().selectUsersByExam(examUuid);
        Map<Integer, String> students = mapperRst.stream().collect(Collectors.toMap(OlexamUser::getId, OlexamUser::getUserName));
        //学生成绩
        List<OlexamStuScore> stuScores = new ArrayList<>();
        //缺考名单
        List<String> noTest = new ArrayList<>();
        for (Integer userId : students.keySet()){
            OlexamStuScore stuScore = stuAnswerService.queryScore(examUuid, userId);
            if (Objects.isNull(stuScore)){
                noTest.add(students.get(userId));
            }else {
                stuScore.setUserName(students.get(userId));
                stuScores.add(stuScore);
            }
        }
        List<OlexamStuScore> scores = stuScores.stream().sorted(Comparator.comparing(OlexamStuScore::getTotalScore).reversed()).collect(Collectors.toList());
        Map<String,Object> rst = new HashMap<>(16);
        rst.put("totalStu", students.size());
        rst.put("noTest", noTest);
        rst.put("stuScores", scores);

        return rst;
    }
}
